<?php
/**
 * Semantic Classes is made up of class-generating functions
 * that dynamically generate context sensitive classes and ids
 * to give unprecedented control over your layout options via CSS.
 * 
 * @package WP_Framework
 * @subpackage Semantic_Classes
 */

// Semantic_Classes
add_filter( 'framework_body_class', 'semantic_body' );
add_filter( 'framework_entry_class', 'semantic_entries' );
add_filter( 'framework_comment_class', 'semantic_comments' );
add_filter( 'post_gallery', 'semantic_gallery' );

/* Define the num val for 'alt' classes (in post DIV and comment LI) */
$semantic_post_alt = 1;
$semantic_comment_alt = 1;

/**
 * semantic_body() - Generates semantic classes for <body> element
 *
 * @since - 0.2
 * @filter semantic_body
 * @uses semantic_time()
 */
function semantic_body( $classes ) {
		global $wp_query, $current_user;

        // Applies the time- and date-based classes (below) to BODY element
        semantic_date_classes( time(), $classes );

        // Special classes for BODY element when a single post
        if ( is_single() ) {
                the_post();

                // Adds classes for the month, day, and hour when the post was published
                if ( isset( $wp_query->post->post_date ) )
                        semantic_date_classes( mysql2date( 'U', $wp_query->post->post_date ), $classes, 's-' );

                // Adds category classes for each category on single posts
                if ( $cats = get_the_category() )
                        foreach ( $cats as $cat )
							if ( $cat )
                                $classes[] = 's-category-' . $cat->slug;
							else
								$classes[] = 's-category-none';

                // Adds tag classes for each tags on single posts
                if ( $tags = get_the_tags() )
                        foreach ( $tags as $tag )
							if ( $tag )
                                $classes[] = 's-tag-' . $tag->slug;
							else
								$classes[] = 's-tag-none';

                // Adds author class for the post author
				if ( get_the_author_login() )
					$s_author = sanitize_title_with_dashes( strtolower( get_the_author_login() ) );
				else
					$s_author = 'none';
                $classes[] = 's-author-' . $s_author;
                rewind_posts();
        }

        // Author name classes for BODY on author archives
        elseif ( is_author() ) {
                $author = $wp_query->get_queried_object();
                $classes[] = 'author';
				if ( $author )
               		$classes[] = 'author-' . $author->user_nicename;
				else
					$classes[] = 'author-none';
        }

        // Category name classes for BODY on category archvies
        elseif ( is_category() ) {
                $cat = $wp_query->get_queried_object();
                $classes[] = 'category';
				if ( $cat )
                	$classes[] = 'category-' . $cat->slug;
				else
					$classes[] = 'category-none';
        }

        // Tag name classes for BODY on tag archives
        elseif ( is_tag() ) {
                $tags = $wp_query->get_queried_object();
                $classes[] = 'tag';
				if ( $tags )
                	$classes[] = 'tag-' . $tags->slug;
				else
					$classes[] = 'tag-none';
        }

        // Page author for BODY on 'pages'
        elseif ( is_page() ) {
                $pageID = $wp_query->post->ID;
				$page_children = wp_list_pages( "child_of=$pageID&echo=0" );
				if ( !$pageID )
					$pageID = 0;
					$page_children = 0;
                
                the_post();
                $classes[] = 'page pageid-' . $pageID;
				
				if ( get_the_author_login() ) {
					$author = sanitize_title_with_dashes( strtolower( get_the_author_login() ) );
				} else {
					$author = 'none';
				}
                $classes[] = 'page-author-' . $author;
                rewind_posts();
        }
		
		// A little browser detection shall we?
		$browser = $_SERVER[ 'HTTP_USER_AGENT' ];
		
		// Mac, PC ...or Linux?
		if ( preg_match( "/Mac/", $browser ) ){
				$classes[] = 'mac';
			
		} elseif ( preg_match( "/Windows/", $browser ) ){
				$classes[] = 'windows';
			
		} elseif ( preg_match( "/Linux/", $browser ) ) {
				$classes[] = 'linux';

		} else {
				$classes[] = 'unknown-os';
		}
		
		// Checks browsers in this order: Chrome, Safari, Opera, MSIE, FF
		// Then, get the browser's version number
		if ( preg_match( "/Chrome/", $browser ) ) {
				$classes[] = 'chrome';

				preg_match( "/Chrome\/(\d.\d)/si", $browser, $matches);
				$ch_version = 'ch' . str_replace( '.', '-', $matches[1] );      
				$classes[] = $ch_version;

		} elseif ( preg_match( "/Safari/", $browser ) ) {
				$classes[] = 'safari';
				
				preg_match( "/Version\/(\d.\d)/si", $browser, $matches);
				$sf_version = 'sf' . str_replace( '.', '-', $matches[1] );      
				$classes[] = $sf_version;
				
		} elseif ( preg_match( "/Opera/", $browser ) ) {
				$classes[] = 'opera';
				
				preg_match( "/Opera\/(\d.\d)/si", $browser, $matches);
				$op_version = 'op' . str_replace( '.', '-', $matches[1] );      
				$classes[] = $op_version;
				
		} elseif ( preg_match( "/MSIE/", $browser ) ) {
				$classes[] = 'msie';
				
				if( preg_match( "/MSIE 6.0/", $browser ) ) {
						$classes[] = 'ie6';
				} elseif ( preg_match( "/MSIE 7.0/", $browser ) ){
						$classes[] = 'ie7';
				} elseif ( preg_match( "/MSIE 8.0/", $browser ) ){
						$classes[] = 'ie8';
				}
				
		} elseif ( preg_match( "/Firefox/", $browser ) && preg_match( "/Gecko/", $browser ) ) {
				$classes[] = 'firefox';
				
				preg_match( "/Firefox\/(\d)/si", $browser, $matches);
				$ff_version = 'ff' . str_replace( '.', '-', $matches[1] );      
				$classes[] = $ff_version;
				
		} else {
				$classes[] = 'unknown-browser';
		}
				
        // And tada!
		return $classes;
}

/**
 * semantic_entries() - Generates semantic classes for each post <div> element
 *
 * @since - 0.2
 * @filter semantic_entries
 * @uses semantic_time()
 */
function semantic_entries( $classes ) {
        global $post, $semantic_post_alt, $entry_first_class;
		
		// add css class to first comment
		if( $entry_first_class == 0 )
			$classes[] = 'first-entry';
			$entry_first_class = 1;
		
        // Author for the post queried
        $classes[] = 'author-' . sanitize_title_with_dashes( strtolower( get_the_author( 'login' ) ) );

        // post_class doesn't do anything for entries that don't have tags
        if ( get_the_tags() == NULL )
			$classes[] = 'untagged';

        // For password-protected posts
        if ( $post->post_password )
			$classes[] = 'protected';

        // Applies the time- and date-based classes
        semantic_date_classes( mysql2date( 'U', $post->post_date ), $classes );

        // If it's the other to the every, then add 'alt' class
        if ( ++$semantic_post_alt % 2 && !is_singular() )
			$classes[] = 'alt';

        // And tada!
		return $classes;
}

/**
 * semantic_comments() - Generates semantic classes for each comment <li> element
 *
 * @since - 0.2
 * @filter semantic_comments
 * @uses semantic_time()
 */
function semantic_comments( $classes ) {
        global $comment, $post, $current_user, $comment_first_class;
		
		// add css class to first comment
		if( $comment_first_class == 0 )
			$classes[] = 'first-comment';
			$comment_first_class = 1;	
		
		// add css class to last comment
		if( $comment->comment_ID == semantic_last_class( 'comment' ) and !$comment_first_class )
			$classes[] = 'last-comment';
				
		// Show commenter's capabilities
		if ( $comment->user_id > 0 && $user = get_userdata( $comment->user_id ) ) {
			$user->wp_capabilities;
			
			if ( array_key_exists( 'administrator', $user->wp_capabilities ) )
				$classes[] = 'administrator administrator-' . $user->user_login;
			elseif ( array_key_exists( 'editor', $user->wp_capabilities ) )
				$classes[] = 'editor editor-' . $user->user_login;
			elseif ( array_key_exists( 'author', $user->wp_capabilities ) )
				$classes[] = 'author author-' . $user->user_login;
			elseif ( array_key_exists( 'contributor', $user->wp_capabilities ) )
				$classes[] = 'contributor contributor-' . $user->user_login;
			elseif ( array_key_exists( 'subscriber', $user->wp_capabilities ) )
				$classes[] = 'subscriber subscriber-' . $user->user_login;
			// For comment authors who are the author of the post
			if ( $post = get_post( $post_id ) ) {
				if ( $comment->user_id === $post->post_author )
					$classes[] = 'entry-author entry-author-' . $user->user_login;
			}
		} else {
			$classes[] = 'reader reader-' . str_replace( ' ', '-', strtolower( $comment->comment_author ) );
		}
		
		// http://microid.org
		$email = get_comment_author_email();
		$uri = get_comment_author_url();
		if ( !empty( $email ) && !empty( $uri ) ) {
			if ( preg_match( '/https:\/\//i', $uri ) )
				$protocal = 'https';
			elseif ( preg_match( '/http:\/\//i', $uri ) )
				$protocal = 'http';
			$microid = "microid-mailto+{$protocal}:sha1:" . sha1( sha1( 'mailto:' . $email ) . sha1( $uri ) );
			$classes[] = $microid;
		}
				
        // If it's the other to the every, then add 'alt' class; collects time- and date-based classes
        semantic_date_classes( mysql2date( 'U', $comment->comment_date ), $classes, 'c-' );

        // Tada again!
		return $classes;
}

/**
 * semantic_last_class() - returns the ID for the last class.
 *
 * @since - 0.3
 */
function semantic_last_class( $type = NULL ){
	global $comment, $post, $wpdb;
	if ( !$type == 'comment' || !$type == 'post' )
		return;

	$post_id = $post->ID;
	
	// type can be post/comment (W.I.P.)
	if ( $type == 'comment' )
		$query = "SELECT * FROM $wpdb->comments WHERE comment_post_ID = $post_id";
	
	if ($type) $get_id = $wpdb->get_results( $query, ARRAY_N );
	
	$last = end( $get_id );
	return $last[0];
}

/**
 * semantic_date_classes() - Generates time- and date-based classes for <body>, post <div>, and comment <li>; relative to GMT (UTC)
 *
 * @since - 0.2
 * @usedby semantic_body(), semantic_entries(), semantic_comments()
 */
function semantic_date_classes( $t, &$classes, $p = '' ) {
        $t = $t + ( get_option( 'gmt_offset' ) * 3600 );
        $classes[] = $p . 'y' . gmdate( 'Y', $t ); // Year
        $classes[] = $p . 'm' . gmdate( 'm', $t ); // Month
        $classes[] = $p . 'd' . gmdate( 'd', $t ); // Day
        $classes[] = $p . 'h' . gmdate( 'H', $t ); // Hour
}

/**
 * semantic_gallery() - Function to filter the [gallery] shortcode. Also eliminates css style rules added when using the [gallery] shortcode.
 *
 * @since - 0.3
 * @todo see if you can improve the functionality, maybe do a subset of JT's cleaner gallery?
 */
function semantic_gallery( $attr ) {
	global $post;
	if ( isset($attr['orderby']) ) {
		$attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
		if ( !$attr['orderby'] )
			unset( $attr['orderby'] );
	}

	extract( shortcode_atts( array(
		'orderby'    => 'menu_order ASC, ID ASC',
		'id'         => $post->ID,
		'itemtag'    => 'dl',
		'icontag'    => 'dt',
		'captiontag' => 'dd',
		'columns'    => 3,
		'size'       => 'thumbnail',
	), $attr ) );

	$id           =  intval($id);
	$orderby      =  addslashes($orderby);
	$attachments  =  get_children( "post_parent=$id&post_type=attachment&post_mime_type=image&orderby={$orderby}" );

	if ( empty($attachments) )
		return null;

	if ( is_feed() ) {
		$output = "\n";
		foreach ( $attachments as $id => $attachment )
			$output .= wp_get_attachment_link( $id, $size, true ) . "\n";
		return $output;
	}

	$listtag     =  tag_escape($listtag);
	$itemtag     =  tag_escape($itemtag);
	$captiontag  =  tag_escape($captiontag);
	$columns     =  intval($columns);
	$itemwidth   =  $columns > 0 ? floor(100/$columns) : 100;

	$output = apply_filters( 'gallery_style', "\n" . '<div class="gallery">', 9 ); // Available filter: gallery_style

	foreach ( $attachments as $id => $attachment ) {
		$img_lnk = get_attachment_link($id);
		$img_src = wp_get_attachment_image_src( $id, $size );
		$img_src = $img_src[0];
		$img_alt = $attachment->post_excerpt;
		if ( $img_alt == null )
			$img_alt = $attachment->post_title;
		$img_rel = apply_filters( 'gallery_img_rel', 'attachment' ); // Available filter: gallery_img_rel
		$img_class = apply_filters( 'gallery_img_class', 'gallery-image' ); // Available filter: gallery_img_class

		$output  .=  "\n\t" . '<' . $itemtag . ' class="gallery-item gallery-columns-' . $columns .'">';
		$output  .=  "\n\t\t" . '<' . $icontag . ' class="gallery-icon"><a href="' . $img_lnk . '" title="' . $img_alt . '" rel="' . $img_rel . '"><img src="' . $img_src . '" alt="' . $img_alt . '" class="' . $img_class . ' attachment-' . $size . '" /></a></' . $icontag . '>';

		if ( $captiontag && trim($attachment->post_excerpt) ) {
			$output .= "\n\t\t" . '<' . $captiontag . ' class="gallery-caption">' . $attachment->post_excerpt . '</' . $captiontag . '>';
		}

		$output .= "\n\t" . '</' . $itemtag . '>';
		if ( $columns > 0 && ++$i % $columns == 0 )
			$output .= "\n</div>\n" . '<div class="gallery">';
	}
	$output .= "\n</div>\n";

	return $output;
}

/* R.I.P. Sandbox */
?>